package com.yazi.mxz.common.service.impl;

import java.util.Calendar;
import java.util.Iterator;

import javax.annotation.Resource;

import com.myframework.smhj.common.exception.MyEntityNotExistsException;
import com.myframework.smhj.common.exception.MyException;
import com.myframework.smhj.common.exception.MyNoPermissionException;
import com.myframework.smhj.common.tool.DateUtil;
import com.myframework.smhj.hibernate.Searching;
import com.myframework.smhj.hibernate.Page;
import com.myframework.smhj.hibernate.dao.BasicService;
import com.myframework.smhj.hibernate.dao.Dao;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.yazi.mxz.common.MyUtil;
import com.yazi.mxz.common.db.dao.GoodsDao;
import com.yazi.mxz.common.db.dao.StoreDao;
import com.yazi.mxz.common.db.dao.StoreGoodsDao;
import com.yazi.mxz.common.db.dao.StoreGoodsPicDao;
import com.yazi.mxz.common.entity.ValueFactory;
import com.yazi.mxz.common.entity.beans.Goods;
import com.yazi.mxz.common.entity.beans.Store;
import com.yazi.mxz.common.entity.beans.StoreGoods;
import com.yazi.mxz.common.entity.enums.StoreGoodsStatus;
import com.yazi.mxz.common.entity.enums.StoreGoodsSyncFields;
import com.yazi.mxz.common.service.StoreGoodsService;

@Service("storeGoodsService")
public class StoreGoodsServiceImpl extends BasicService<StoreGoods> implements
		StoreGoodsService {
	private static Logger log = LoggerFactory
			.getLogger(StoreGoodsServiceImpl.class);

	@Resource
	StoreGoodsDao storeGoodsDao;
	@Resource
	GoodsDao goodsDao;
	@Resource
	StoreGoodsPicDao storeGoodsPicDao;
	@Resource
	StoreDao storeDao;

	@Override
	protected Dao<StoreGoods> getDao() {
		return storeGoodsDao;
	}

	@Override
	public Page<StoreGoods> listByGtUpdateTime(StoreGoods sg, Searching si) {
		log.debug("listByGtUpdateTime：");
		return storeGoodsDao.listByGtUpdateTime(sg, si);
	}

	@Override
	public Page<StoreGoods> listFromSameOrder(long storeGoodsId, Searching si) {
		log.debug("listFromSameOrder：storeGoodsId={}", storeGoodsId);
		return storeGoodsDao.listFromSameOrder(storeGoodsId, si);
	}

	@Override
	public StoreGoods edit(StoreGoods sg) throws MyException {
		log.debug("edit：storeGoodsId={}", sg.getStoreGoodsId());
		StoreGoods dest = storeGoodsDao.get(sg.getStoreGoodsId());

		/**
		 * 找出旧图片列表中不存在于新图片列表中的图片，便将其文件删除，<br>
		 * 注意：请根据系统架构决定是否允许删除原文件，来决定是否启用本代码块。<br>
		 * 一般来讲，系统中的图片不会被重用时，可开启本代码实现删除不需要的文件，节省空间。
		 */
		/*
		StoreGoodsPic newPic;
		boolean oneToDel;
		List<StoreGoodsPic> delPics = new ArrayList<StoreGoodsPic>();// 要删除的图片（文件）
		Iterator<StoreGoodsPic> oldPics = dest.getStoreGoodsPics().iterator();// 旧的图片	
		while (oldPics.hasNext()) {
			StoreGoodsPic oldPic = oldPics.next();
			oneToDel = true;
			Iterator<StoreGoodsPic> newPics = sg.getStoreGoodsPics().iterator();
			while (newPics.hasNext()) {
				newPic = newPics.next();
				if (oldPic.getPic().equals(newPic.getPic())) {
					oneToDel = false;
				}
			}
			if (oneToDel) {
				delPics.add(oldPic);
			}
		}
		*/

		ValueFactory.combine(sg, dest);
		
		// 计费库存转换为出售出库(取整)
		if (null != dest.getSellUnit() && dest.getUnitConvert() != 0) {
			dest.setStockConvert(MyUtil.numRoundDown(
					dest.getStock() / dest.getUnitConvert(), 0).floatValue());
		} else {
			dest.setStockConvert(MyUtil.numRoundDown(dest.getStock(), 2)
					.floatValue());
		}
		dest.setUpdateTime(DateUtil.getTimeStamp());
		dest = storeGoodsDao.merge(dest);
		
		/**
		 * 在所有数据库操作完成后，再删除需要删除的文件。<br>
		 * 注意：请根据系统架构来决定是否允许删除原文件，并启用上面被注释的代码块，<br>
		 * 然后在这里删除相应的图片文件<br>
		 * 一般来讲，系统中的图片不会被重用时，可开启本代码实现删除不需要的文件，节省空间。
		 */
		/*
		for (StoreGoodsPic pic : delPics) {
			String file = pic.getPic();
			// TODO 删除file对应的文件
		}
		*/
		
		return dest;
	}

	@Override
	public StoreGoods editByStore(Store store, StoreGoods sg)
			throws MyException {
		log.debug("editByStore：storeId={},storeGoodsId={}", store.getStoreId(),
				sg.getStoreGoodsId());

		StoreGoods dest = storeGoodsDao.get(sg.getStoreGoodsId());
		
		// 不是指定店铺的商品
		if (null == dest || !dest.getStore().equals(store)) {
			throw new MyException();
		}

		return edit(dest);
	}

	@Override
	public void addByStore(Store store, long[] goodsIds) throws MyException {
		log.debug("addByStore：storeId={},goodsIds={}", store.getStoreId(),
				goodsIds);

		for (long goodsId : goodsIds) {

			Goods goods = goodsDao.get(goodsId);

			if (null == goods) {
				throw new MyEntityNotExistsException();
			}
			if (!goods.getCompany().equals(store.getCompany())) {
				throw new MyNoPermissionException();
			}

			// storeGoods for search
			StoreGoods sg4s = new StoreGoods();
			sg4s.setGoods(goods);
			sg4s.setStore(store);
			int count = storeGoodsDao.countByExample(sg4s);

			// 店铺中已经存在此商品,则跳过
			if (count > 0) {
				continue;
			}

			StoreGoods storeGoods = newByGoods(goods);
			storeGoods.setStore(store);
			ValueFactory.validate(storeGoods);
			storeGoods.setStoreGoodsId(null);
			storeGoodsDao.persist(storeGoods);
		}

	}

	@Override
	public StoreGoods addForStore(long storeId, Goods goods) {
		log.debug("addForStore：storeId={},goodsId={}", storeId,
				goods.getGoodsId());

		Store store = new Store();
		store.setStoreId(storeId);

		StoreGoods storeGoods = newByGoods(goods);
		ValueFactory.validate(storeGoods);
		storeGoods.setStore(store);
		storeGoods.setStoreGoodsId(null);
		return storeGoodsDao.persist(storeGoods);
	}

	@Override
	public void editAllDeal() {
		log.debug("editAllDeal：");
		storeGoodsDao.updateAllDealByTime();
	}

	@Override
	public void editWeekDeal() {
		log.debug("editWeekDeal：");
		Long nowTime = Calendar.getInstance().getTimeInMillis();

		Calendar c = Calendar.getInstance();
		c.add(Calendar.WEEK_OF_YEAR, -1);

		storeGoodsDao.updateWeekDealByTime(c.getTimeInMillis(), nowTime);
	}

	@Override
	public void editMonthDeal() {
		log.debug("editMonthDeal：");
		Long nowTime = Calendar.getInstance().getTimeInMillis();

		Calendar c = Calendar.getInstance();
		c.add(Calendar.MONTH, -1);

		storeGoodsDao.updateMonthDealByTime(c.getTimeInMillis(), nowTime);
	}

	@Override
	public Page<StoreGoods> listByStockGtZero(StoreGoods sg, Searching si) {
		log.debug("listByStockGtZero: storeId={}", sg.getStore().getStoreId());
		return storeGoodsDao.listByStockGtZero(sg, si);
	}

	@Override
	public Page<StoreGoods> listByBarCodeLike(StoreGoods sg, Searching si) {
		log.debug("listByBarCodeLike: storeId={}", sg.getStore().getStoreId());
		return storeGoodsDao.listByBarCodeLike(sg, si);
	}

	@Override
	public void editByGoodsId(long goodsId, Long sync) {
		if (null == sync || sync == 0) {
			return;
		}

		log.debug("editByGoodsId: goodsId={},sync={}", goodsId, sync);

		Goods g = goodsDao.get(goodsId);
		if (null == g) {
			return;
		}

		Iterator<StoreGoods> its = g.getStoreGoodses().iterator();

		while (its.hasNext()) {

			StoreGoods sg = its.next();

			if ((sync & (1 << StoreGoodsSyncFields.CATEGORY.ordinal())) > 0) {
				sg.setCategory(g.getCategory());
				sg.setCategoryPath(g.getCategoryPath());
			}
			if ((sync & (1 << StoreGoodsSyncFields.DESCR_DEF.ordinal())) > 0) {
				sg.setDescription(g.getDescrDef());
			}
			if ((sync & (1 << StoreGoodsSyncFields.GOODS_CLASSIFY.ordinal())) > 0) {
				sg.setGoodsClassify(g.getGoodsClassify());
			}
			if ((sync & (1 << StoreGoodsSyncFields.KEYWORDS.ordinal())) > 0) {
				sg.setKeywords(g.getKeywords());
			}
			if ((sync & (1 << StoreGoodsSyncFields.PIC.ordinal())) > 0) {
				sg.setPic(g.getPic());
			}
			if ((sync & (1 << StoreGoodsSyncFields.PRICE.ordinal())) > 0) {

				if (sg.getAtDiscount()) {
					sg.setOriginalPrice(g.getPrice());
				} else {
					sg.setPrice(g.getPrice());
				}

			}
			if ((sync & (1 << StoreGoodsSyncFields.SELL_DEF.ordinal())) > 0) {
				sg.setSellDef(g.getSellDef());
			}
			if ((sync & (1 << StoreGoodsSyncFields.SELL_EXT.ordinal())) > 0) {
				sg.setSellExt(g.getSellExt());
			}
			if ((sync & (1 << StoreGoodsSyncFields.SELL_MIN.ordinal())) > 0) {
				sg.setSellMin(g.getSellMin());
			}
			if ((sync & (1 << StoreGoodsSyncFields.SELL_UNIT.ordinal())) > 0) {
				sg.setSellUnit(g.getSellUnit());
			}
			if ((sync & (1 << StoreGoodsSyncFields.STOCK_END.ordinal())) > 0) {
				sg.setStockEnd(g.getStockEnd());
			}
			if ((sync & (1 << StoreGoodsSyncFields.SUB_TITLE.ordinal())) > 0) {
				sg.setSubTitle(g.getSubTitle());
			}
			if ((sync & (1 << StoreGoodsSyncFields.TITLE.ordinal())) > 0) {
				sg.setTitle(g.getTitle());
			}
			if ((sync & (1 << StoreGoodsSyncFields.UNIT.ordinal())) > 0) {
				sg.setUnit(g.getUnit());
			}

			storeGoodsDao.merge(sg);
		}
	}

	@Override
	public void editStockConvertByStore(Store store, long storeGoodsId,
			float stockConvert) throws MyException {
		log.debug(
				"editStockConvertByStore: storeId={},storeGoodId={},stockConvert={}",
				new Object[] { store.getStoreId(), storeGoodsId, stockConvert });

		StoreGoods sg = storeGoodsDao.get(storeGoodsId);

		if (null == sg) {
			throw new MyEntityNotExistsException();
		}
		if (!sg.getStore().equals(store)) {
			throw new MyNoPermissionException();
		}

		sg.setStockConvert(stockConvert);

		// 重新计算折算率
		if (null != sg.getSellUnit() && sg.getStock() > 0) {
			sg.setUnitConvert(MyUtil.numRoundDown(stockConvert / sg.getStock(),
					1).floatValue());
		}

		storeGoodsDao.merge(sg);
	}

	@Override
	public void editStatusByStore(Store store, long[] storeGoodsIds,
			StoreGoodsStatus status) throws MyException {

		log.debug("editStatusByStore：storeId={},storeGoodsIds={},status={}",
				new Object[] { store.getStoreId(), storeGoodsIds, status });

		for (long storeGoodsId : storeGoodsIds) {

			StoreGoods sg = storeGoodsDao.get(storeGoodsId);

			if (null == sg) {
				throw new MyEntityNotExistsException();
			}
			if (!sg.getStore().equals(store)) {
				throw new MyNoPermissionException();
			}

			sg.setStatus(status.ordinal());
			storeGoodsDao.merge(sg);
		}

	}

	private StoreGoods newByGoods(Goods g) {
		StoreGoods sg = new StoreGoods();
		sg.setAddTime(DateUtil.getTimeStamp());
		sg.setBarCode(g.getBarCode());
		sg.setCategory(g.getCategory());
		sg.setCategoryPath(g.getCategoryPath());
		sg.setDescription(g.getDescrDef());
		sg.setGoods(g);
		sg.setGoodsClassify(g.getGoodsClassify());
		sg.setKeywords(g.getKeywords());
		sg.setName(g.getName());
		sg.setPic(g.getPic());
		sg.setPrice(g.getPrice());
		sg.setSellDef(g.getSellDef());
		sg.setSellExt(g.getSellExt());
		sg.setSellMin(g.getSellMin());
		sg.setSellUnit(g.getSellUnit());
		sg.setStockEnd(g.getStockEnd());
		sg.setSubTitle(g.getSubTitle());
		sg.setTitle(g.getTitle());
		sg.setUnit(g.getUnit());
		sg.setUnitConvert(g.getUnitConvert());
		sg.setUpdateTime(DateUtil.getTimeStamp());
		return sg;
	}

}
